package com.itmake.sample.itext.utils;

import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.*;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.font.FontProvider;
import com.itmake.sample.itext.model.po.WaterText;
import com.itmake.sample.itext.model.po.WaterImage;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.net.MalformedURLException;
import java.util.List;

/**
 * itextpdf 工具类
 *
 * @author Amjacks
 * @since 2023/08/10
 */
@Component
public class PdfUtil {

    /**
     * html转pdf
     *
     * @param html        html
     * @param cacheStream 缓存流
     */
    public void htmlToPdf(String html, ByteArrayOutputStream cacheStream) throws IOException {
        // 1、转换为pdf
        PdfWriter convertToPdf = new PdfWriter(cacheStream);
        // 2、添加参数
        ConverterProperties pro =  new ConverterProperties();
        FontProvider fontProvider = new DefaultFontProvider();
        fontProvider.addSystemFonts();
        pro.setFontProvider(fontProvider);
        // 3、开始转换并缓存至缓存输出流
        HtmlConverter.convertToPdf(html, convertToPdf, pro);
        // 4、关闭流
        convertToPdf.flush();
        convertToPdf.close();
    }

    /**
     * 添加水印
     *
     * @param outputStream   输出流
     * @param cacheStream    缓存流
     * @param waterImageList 水印图像列表
     */
    public void addWaterMark(OutputStream outputStream, ByteArrayOutputStream cacheStream, List<WaterImage> waterImageList) throws IOException {
        addWaterMark(outputStream, cacheStream, waterImageList, null);
    }

    /**
     * 添加水印
     *
     * @param outputStream   输出流
     * @param cacheStream    缓存流
     * @param waterImageList 水印图像列表
     * @param waterTextList  水印文本列表
     */
    public void addWaterMark(OutputStream outputStream,
                             ByteArrayOutputStream cacheStream,
                             List<WaterImage> waterImageList,
                             List<WaterText> waterTextList) throws IOException {
        // 读取为pdf并添加水印
        PdfWriter addWaterMark = new PdfWriter(outputStream);
        // 读取缓存
        InputStream inputStream = new ByteArrayInputStream(cacheStream.toByteArray());
        // 构建pdf文档树
        PdfReader reader = new PdfReader(inputStream);
        // 构建doc页面
        PdfDocument pdfDocument = new PdfDocument(reader, addWaterMark);
        pdfDocument.setDefaultPageSize(PageSize.A4);
        pdfDocument.getNumberOfPages();
        for (int i = 1; i <= pdfDocument.getNumberOfPages(); i++) {
            PdfPage page = pdfDocument.getPage(i);
            if (!CollectionUtils.isEmpty(waterTextList)) {
                addTextWaterMark(page, waterTextList);
            }
            if (!CollectionUtils.isEmpty(waterImageList)) {
                addImgWaterMark(page, waterImageList);
            }
            page.flush();
        }

        // 关闭资源
        pdfDocument.close();
        reader.close();
        inputStream.close();
        addWaterMark.flush();
        addWaterMark.close();
    }

    /**
     * 添加图片水印
     *
     * @param page           页面
     * @param waterImageList 水印列表
     */
    private void addImgWaterMark (PdfPage page, List<WaterImage> waterImageList) throws MalformedURLException {
        PdfDocument document = page.getDocument();
        Document doc = new Document(document);
        // 添加水印
        for (WaterImage waterImage : waterImageList) {
            Image readImg = new Image(ImageDataFactory.create(waterImage.getUrlPath()));
            Image srcImage = setImgWaterMark(document, readImg);
            srcImage.scaleToFit(waterImage.getOffsetX(), waterImage.getOffsetY());
            srcImage.setMarginLeft(waterImage.getOffsetX());
            srcImage.setMarginTop(waterImage.getOffsetY());
            srcImage.setRotationAngle(waterImage.getDegree());
            srcImage.setOpacity(waterImage.getAlpha());
            doc.add(srcImage);
        }
    }

    /**
     * 添加文字水印
     *
     * @param page           页面
     * @param waterTextList  水印列表
     */
    private void addTextWaterMark (PdfPage page, List<WaterText> waterTextList) {
        PdfDocument document = page.getDocument();
        Document doc = new Document(document);
        // 添加水印
        for (WaterText waterText : waterTextList) {
            Paragraph paragraph = new Paragraph(waterText.getText());
            paragraph.setMarginLeft(waterText.getOffsetX());
            paragraph.setMarginTop(waterText.getOffsetY());
            paragraph.setOpacity(waterText.getAlpha());
            paragraph.setRotationAngle(waterText.getDegree());
            paragraph.setFontColor(ColorConstants.RED);
            doc.add(paragraph);
        }
    }

    /**
     * 设置图片水印
     *
     * @param pdfDoc    pdf文档
     * @param watermark 水印
     * @return {@link Image}
     */
    private Image setImgWaterMark(PdfDocument pdfDoc, Image watermark) {
        float width = watermark.getImageScaledWidth();
        float height = watermark.getImageScaledHeight();
        PdfFormXObject template = new PdfFormXObject(new Rectangle(width, height));
        new Canvas(template, pdfDoc)
                .add(watermark)
                .close();
        return new Image(template);
    }
}
